//------------------------------------------------------------------------------------
// sme_api.c
//
// Copyright(C) 2002 Winbond Electronics Corp.
//
//
//------------------------------------------------------------------------------------
#include "os_common.h"

//------------------------------------------------------
// For All function
// return : 0  Successful operation
//			-1 Fail operation
//------------------------------------------------------
CHAR sme_get_connect_status(void *pcore_data, UCHAR *pstatus)
{
	PWB32_ADAPTER Adapter = pcore_data;
	*pstatus = MEDIA_STATE_DISCONNECTED;

	if ( CURRENT_LINK_ON )
		*pstatus = MEDIA_STATE_CONNECTED;

	return 0;
}

CHAR sme_get_bssid(void *pcore_data, UCHAR *pbssid)
{
	PWB32_ADAPTER	Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		OS_MEMORY_COPY( pbssid, psBSS(psLOCAL->wConnectedSTAindex)->abBssID, MAC_ADDR_LENGTH );
		return 0;
	}
	return -1;
}

CHAR sme_get_desired_bssid(void *pcore_data, UCHAR *pbssid)
{
	PWB32_ADAPTER	Adapter = (PWB32_ADAPTER)pcore_data;

	OS_MEMORY_COPY( pbssid, psSME->abDesiredBSSID, MAC_ADDR_LENGTH );
	return 0;
} 

CHAR sme_set_desired_bssid(void *pcore_data, UCHAR *pbssid)
{
	PWB32_ADAPTER	Adapter = (PWB32_ADAPTER)pcore_data;

	OS_MEMORY_COPY( psSME->abDesiredBSSID, pbssid, MAC_ADDR_LENGTH );
	return 0;
}

CHAR sme_get_ssid(void *pcore_data, UCHAR *pssid, UCHAR *pssid_len)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*pssid_len = psBSS(psLOCAL->wConnectedSTAindex)->SSID.Length;
		OS_MEMORY_COPY( pssid, psBSS(psLOCAL->wConnectedSTAindex)->SSID.SSID, *pssid_len );
		return 0;
	}
	return -1;
}

CHAR sme_get_desired_ssid(void *pcore_data, UCHAR *pssid, UCHAR *pssid_len)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pssid_len = psSME->sDesiredSSID.Length;
	OS_MEMORY_COPY( pssid, psSME->sDesiredSSID.SSID, psSME->sDesiredSSID.Length );
	return 0;
}

CHAR sme_set_desired_ssid(void *pcore_data, UCHAR *pssid, UCHAR ssid_len)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	K_MSG	sSmeMsg;

	//20050621 add to overcome the bug that tx will be pended if reveived disassoc. request
	//before.(Scan_stop message will set pMds->ScanTxPause true.)
	Adapter->Mds.TxPause = FALSE;  // Enable Tx frame
	Adapter->Mds.ScanTxPause = FALSE;

	if ((psLOCAL->RadioOffStatus.boHwRadioOff == TRUE) ||
		(psLOCAL->RadioOffStatus.boSwRadioOff == TRUE))
		return -1;	//to avoid to start an IBSS

	//WPA countermeasure will block the association
	if ((psSME->encrypt_status == ENCRYPT_TKIP) && //TKIP
		(Adapter->Mds.boCounterMeasureBlock == 1))
		return -1;
	//if ((ssid_len == 8) &&
	//	(memcpy(pssid, ddd, ssid_len)==0))
	//	return -1;

	psSME->sDesiredSSID.Length = ssid_len;
	OS_MEMORY_COPY( psSME->sDesiredSSID.SSID, pssid, ssid_len );

	// To avoid use the old desired BSSID if the desired SSID length is 0
//	OS_MEMORY_COPY( psSME->abDesiredBSSID, "\xff\xff\xff\xff\xff\xff", MAC_ADDR_LENGTH );

	sSmeMsg.wMsgType = SMEMSG_JOIN_REQ;
	sSmeMsg.wInstance = 0;
	sSmeMsg.pMsgPtr = NULL;
	SME_Entry(Adapter, &sSmeMsg);

	return 0;
}

CHAR sme_get_bss_type(void *pcore_data, UCHAR *pbss_type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*pbss_type = psBSS(psLOCAL->wConnectedSTAindex)->bBssType;
		return 0;
	}
	return -1;
}

CHAR sme_get_desired_bss_type(void *pcore_data, UCHAR *pbss_type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pbss_type = psSME->bDesiredBSSType;
	return 0;
}

CHAR sme_set_desired_bss_type(void *pcore_data, UCHAR bss_type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psSME->bDesiredBSSType = bss_type;
	hal_clear_all_key(&Adapter->sHwData);
	//psSME->encrypt_status = ENCRYPT_DISABLE;
	psSME->pairwise_key_ok = FALSE;
	psSME->_dot11WEPDefaultKeyID = 0;
	psSME->group_key_ok = FALSE;

	return 0;
}

CHAR sme_get_fragment_threshold(void *pcore_data, ULONG *pthreshold)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pthreshold = (ULONG)Adapter->Mds.TxFragmentThreshold;
	return 0;
}

CHAR sme_set_fragment_threshold(void *pcore_data, ULONG threshold)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(threshold<256 || threshold>2346)
		return -1;
	threshold &= ~0x01;//Even only
	Adapter->Mds.TxFragmentThreshold = (USHORT)threshold;
	return 0;
}

CHAR sme_get_rts_threshold(void *pcore_data, ULONG *pthreshold)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pthreshold = (ULONG)Adapter->Mds.TxRTSThreshold;
	return 0;
}

CHAR sme_set_rts_threshold(void *pcore_data, ULONG threshold)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(threshold>2347)
		return -1;
	//TODO: hal_set_rts_threshold() will be implemented by S/W
	//hal_set_rts_threshold(&Adapter->sHwData, threshold);
	Adapter->Mds.TxRTSThreshold =(USHORT)threshold;
	return 0;
}

CHAR sme_get_rssi(void *pcore_data, LONG *prssi)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	WB_BSSDESCRIPTION		*pconn_bss = NULL; // important!!!


	// 1.0.24.0 For NJRC
	*prssi = -110;
	if( !sme_get_connected_bss( pcore_data, (PVOID)&pconn_bss ) )
	{
		if (psBSS(psLOCAL->wConnectedSTAindex)->bBssType == IBSS_NET)
			pconn_bss = psBSS(psLOCAL->JoinerInIbss[1]);

		if (boIsReceiveBeacon(Adapter))
			*prssi = hal_get_rssi( &Adapter->sHwData, pconn_bss->HalRssi, MAX_ACC_RSSI_COUNT );
	}
	return 0;
}

CHAR sme_get_beacon_period(void *pcore_data, USHORT *pbeacon_period)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*pbeacon_period = psBSS(psLOCAL->wConnectedSTAindex)->Beacon_Period;
		return 0;
	}
	return -1;
}

CHAR sme_set_beacon_period(void *pcore_data, USHORT beacon_period)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psSME->wBeaconPeriod = beacon_period;
	return 0;
}

CHAR sme_get_atim_window(void *pcore_data, USHORT *patim_window)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*patim_window = *(USHORT *)psBSS(psLOCAL->wConnectedSTAindex)->IBSS_Parameter_Set.ATIM_Window;
		return 0;
	}
	return -1;
}

CHAR sme_set_atim_window(void *pcore_data, USHORT atim_window)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psSME->wATIM_Window = atim_window;
	return 0;
}

CHAR sme_get_current_channel(void *pcore_data, UCHAR *pcurrent_channel)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*pcurrent_channel = psBSS(psLOCAL->wConnectedSTAindex)->DS_Parameter_Set.Current_Channel;
		return 0;
	}
	return -1;
}

CHAR sme_get_current_band(void *pcore_data, UCHAR *pcurrent_band)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*pcurrent_band = psBSS(psLOCAL->wConnectedSTAindex)->band;
		return 0;
	}
	return -1;
}

CHAR sme_set_current_channel(void *pcore_data, UCHAR current_channel)
{
	//PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	//psSME->bCurrentChannel = current_channel;
	return 0;
}

CHAR sme_get_scan_bss_count(void *pcore_data, UCHAR *pcount)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	vBSSfoundList(Adapter);
	*pcount = psLOCAL->BssListCount;
	return 0;
}

CHAR sme_get_scan_bss(void *pcore_data, UCHAR index, void **ppbss)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	//Assume the sme_get_scan_bss_count() will be called firstly.
	*ppbss = psBSS(psLOCAL->BssListIndex[index]);
	return 0;
}

CHAR sme_get_connected_bss(void *pcore_data, void **ppbss_now)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if(psLOCAL->wConnectedSTAindex)
	{
		*ppbss_now = psBSS(psLOCAL->wConnectedSTAindex);
		return 0;
	}
	return -1;
}

CHAR sme_get_auth_mode(void *pcore_data, UCHAR *pauth_mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pauth_mode = psSME->bDesiredAuthMode;
	return 0;
}

CHAR sme_set_auth_mode(void *pcore_data, UCHAR auth_mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psSME->bDesiredAuthMode = auth_mode;
	return 0;
}

//replace by sme_get_encryption_status and sme_set_encryption_status
/*
CHAR sme_get_wep_mode(void *pcore_data, UCHAR *pwep_mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pwep_mode = psSME->_dot11PrivacyInvoked;
	return 0;
}

CHAR sme_set_wep_mode(void *pcore_data, UCHAR wep_mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psSME->_dot11PrivacyInvoked           = wep_mode;
	psSME->_dot11PrivacyOptionImplemented = wep_mode;
	if(wep_mode)
		psSME->_WEPKeyLength = (psSME->key_length==5) ? WEPKEY_64 : WEPKEY_128;
	else
		psSME->_WEPKeyLength = WEPKEY_DISABLED;

	//??clear WEP table or not because WEP mode change??
	return 0;
}
*/

CHAR sme_set_add_wep(void *pcore_data, ULONG key_index, ULONG key_len,
					UCHAR *address, UCHAR *key)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	ULONG i;
	CHAR ret = -1;
	UCHAR		key_type;

	do
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("OID Key idx =[%x] length = %d Content = ", key_index, key_len));
		for(i=0; i<key_len; i++)
			WBDEBUG(("[%x]%c ",key[i], key[i]));
		WBDEBUG(("\n"));
		#endif

		//Only 40 and 104 bit only
		switch (key_len)
		{
			case 5:
				key_type = HAL_KEYTYPE_WEP40;	break;
			case 13:
				key_type = HAL_KEYTYPE_WEP104;	break;
			default:
				return ret;
		}

		//psSME->key_length = (UCHAR)key_len;// Setting the Key length

		//Setting Global Key
		if((key_index & BIT(30)) == 0)
		{
			//Is valid Index?
			i = key_index & 0x3fffffff;
			if(i>3)
				return ret;
			if (key_index & BIT(31))
				psSME->_dot11WEPDefaultKeyID = i;// Default Key index setting
			hal_set_default_key(&Adapter->sHwData,
								(UCHAR)i,
								0,
								1,
								NULL,
								NULL,
								(UCHAR)key_type,
								(UCHAR)key_len,
								key);
			psSME->group_key_ok = TRUE;
		}
		else	//Per client key setting
		{
			//Is valid Index?
			//TODO: the index of per client key should be zero
			if((key_index & 0x3fffffff)!= 0)
				return ret;
			hal_set_mapping_key(&Adapter->sHwData,
								address,
								0,
								1,
								NULL,
								NULL,
								(UCHAR)key_type,
								(UCHAR)key_len,
								key);
			psSME->pairwise_key_ok = TRUE;
		}
		ret = 0;
	}while(FALSE);

	return ret;
}

CHAR sme_set_disassociate(void *pcore_data)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	K_MSG	sMsg;
	USHORT	wReasonCode, IsDisassoc;

	//#ifdef _WPA_
	psSME->pairwise_key_ok = 0;
	psSME->group_key_ok = 0;
	psSME->wpa_ok = 0;
	//#endif
	IsDisassoc = TRUE;
	sMsg.wMsgType = SCANMSG_STOP_SCAN;
	sMsg.pMsgPtr = &IsDisassoc;
	Scan_Entry(Adapter, &sMsg);

	if(psLOCAL->wConnectedSTAindex)
	{
		wReasonCode = DISASS_REASON_LEFT_BSS;
		sMsg.wMsgType = SMEMSG_DISASSOC_REQ;
		sMsg.pMsgPtr = &wReasonCode;
		SME_Entry(Adapter, &sMsg);
		return 0;
	}
	return 0;
}

CHAR sme_get_power_mode(void *pcore_data, UCHAR *pmode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if (psSME->bDesiredPowerSave)
		*pmode = 2;	//FAST_PSP
	else
		*pmode = 0;	//CAM
	return 0;
}

CHAR sme_set_power_mode(void *pcore_data, UCHAR mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	K_MSG	sSmeMsg;
	UCHAR		PsMode;

	if (mode == 0)	//CAM
	{
		psSME->bDesiredPowerSave = 0;

		//wake up the H/W
		PsMode =  PWR_ACTIVE;
		sSmeMsg.wMsgType = SMEMSG_POWERSAVE_REQ;
		sSmeMsg.pMsgPtr = &PsMode;
		SME_Entry(Adapter, &sSmeMsg);
	}
	else	//MAX_PSP or FAST_PSP
		psSME->bDesiredPowerSave = 1;
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("[Set POWER MODE] psSME->bDesiredPowerSave = %d\n", psSME->bDesiredPowerSave));
	#endif
	return 0;
}

CHAR sme_set_bssid_list_scan(void *pcore_data, void *pscan_para)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	K_MSG	sSmeMsg;
	SCAN_REQ_PARA	sScanReqPara;

	sSmeMsg.wMsgType = SMEMSG_SCAN_REQ;
	sScanReqPara.sChannelList.Count = 0;
	if (pscan_para == NULL)
	{
		//sScanReqPara.ScanType = PASSIVE_SCAN;
		sScanReqPara.ScanType = ACTIVE_SCAN;
		Scan_SetScanChanRange(Adapter, &sScanReqPara);
		//Use broadcast SSID
		sScanReqPara.sSSID.Element_ID = ELEMENT_ID_SSID;
		sScanReqPara.sSSID.Length = 0;
		sSmeMsg.pMsgPtr = &sScanReqPara;
	}
	else
	{
		sSmeMsg.pMsgPtr = (psSCAN_REQ_PARA)pscan_para;
	}
	SME_Entry(Adapter, &sSmeMsg);
	return 0;
}


//----------- WKChen add ------------------
void sme_get_encryption_status(void *pcore_data, UCHAR *EncryptStatus)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	UCHAR	EncryptTmp;

	EncryptTmp = psSME->encrypt_status;
	if ((psSME->pairwise_key_ok != TRUE) && (psSME->group_key_ok != TRUE))
	{
		switch(EncryptTmp)
		{
			case ENCRYPT_WEP:
			case ENCRYPT_TKIP:
			case ENCRYPT_CCMP:
				*EncryptStatus = EncryptTmp + 1;	//KeyAbsent
				break;
			default:
				*EncryptStatus = EncryptTmp;
				break;
		}
	}
	else
		*EncryptStatus = EncryptTmp;
}

void sme_set_encryption_status(void *pcore_data, UCHAR EncryptStatus)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	//if( psSME->encrypt_status != WEP_DISABLE )
	//if( psSME->encrypt_status != ENCRYPT_DISABLE )
      //  return;
	
	psSME->encrypt_status = EncryptStatus;
	if ((EncryptStatus == ENCRYPT_WEP) ||
		(EncryptStatus == ENCRYPT_TKIP) ||
		(EncryptStatus == ENCRYPT_CCMP))
	{
		psSME->_dot11PrivacyInvoked = TRUE;
		psSME->_dot11PrivacyOptionImplemented = TRUE;
		//TODO:
		psSME->wCapabilityInfo |= 0x0010;	//privacy
	}
	else
	{
		psSME->_dot11PrivacyInvoked = FALSE;
		psSME->_dot11PrivacyOptionImplemented = FALSE;
		//TODO: clear privacy
		psSME->wCapabilityInfo &= 0xffef;	//no privacy
	}
}

CHAR sme_add_key(void		*pcore_data,
					ULONG		key_index,
					UCHAR		key_len,
					UCHAR		key_type,
					UCHAR		*key_bssid,
					//UCHAR		*key_rsc,
					UCHAR		*ptx_tsc,
					UCHAR		*prx_tsc,
					UCHAR		*key_material)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	UCHAR	auth_mode;
        UCHAR *tx_key, *rx_key;
        tx_key=NULL;
        rx_key=NULL;

	//psSME->_dot11WEPDefaultKeyID = key_index & 0xff;

	// Save TKIP MIC Key
	if (key_type == HAL_KEYTYPE_TKIP)
	{
		sme_get_auth_mode(pcore_data, &auth_mode);
		switch (auth_mode)
		{
			case WPA_AUTH:
			case WPAPSK_AUTH:
			#ifdef _WPA2_
			case WPA2_AUTH:
			case WPA2PSK_AUTH:
			#endif //end def _WPA2_
				if (key_index & BIT(28))//shift 28 bits
				{
					tx_key = key_material + 16;
					rx_key = key_material + 24;
				}
				else
				{
					tx_key = key_material + 24;
					rx_key = key_material + 16;
				}
				break;
			case WPANONE_AUTH:
				tx_key = rx_key = key_material + 16;
				break;
			default:
				//return -1;	//2c_wlan_randomoids test item in HCT12.0 will set
								//auth mode as AuthModeShared but set key with 32 byte
								//key length.
				tx_key = rx_key = key_material + 16;
				break;
		}
	}

	if ((key_index & BIT(30)) == 0)
    {
		//group key: set the Temporal key of Phase 1
		psSME->key_length=key_len;//added by WS 05/29/04
		if (key_index & BIT(31))//Rx or Tx key
		{
			// Group Key used to TX/RX
			#ifdef _PE_STATE_DUMP_
			WBDEBUG(("Update group key for TX/RX.\n"));
			#endif
			//Minimum number of supported group keys is 4. (XP designed guidelines)
			psSME->_dot11WEPDefaultKeyID = key_index & 0xff;
			//hal_clear_all_default_key(&Adapter->sHwData); // TODO: 0627 kevin
	    	hal_set_default_key(&Adapter->sHwData,
        						(UCHAR)(key_index & 0xFF),
                	    	    0,
                    	    	1,
								ptx_tsc, prx_tsc,
                            	(UCHAR)key_type,
								(UCHAR)key_len,
                            	key_material);
			psSME->group_key_type = key_type;
		}
		else
		{
			// Group Key used to RX only
			#ifdef _PE_STATE_DUMP_
			WBDEBUG(("Update group key for RX.\n"));
			#endif
	    	hal_set_default_key(&Adapter->sHwData,
        						(UCHAR)(key_index & 0xFF),
                	    	    0,
                    	    	1,
								ptx_tsc, prx_tsc,
                            	(UCHAR)key_type,
								(UCHAR)key_len,
                            	key_material);
			psSME->pairwise_key_type = key_type;
		}
		// save group mic key
		if (key_type == HAL_KEYTYPE_TKIP)
		{
			OS_MEMORY_COPY( psSME->group_tx_mic_key, tx_key, 8 );
			OS_MEMORY_COPY( psSME->group_rx_mic_key, rx_key, 8 );
		}
		psSME->group_key_ok = TRUE;
		//TODO:
		//#ifdef _WPA_
		psSME->wpa_ok = 1;
		//#endif
		#ifdef _WPA2_
		   OS_PMKID_STATUS_EVENT( Adapter );
		#endif
	}
    else
    {
		if (key_index & BIT(31))
		{
			// Pairwise Key used to TX/RX
			#ifdef _PE_STATE_DUMP_
			WBDEBUG(("Update pairwise key for TX/RX.\n"));
			#endif
			if (key_index & 0xFF)
			{
				// [IEEE 802.11 Network Adapter Design Guidelines for WinXP v2.1]
				// the key index should be set to zero for a pairwise key.
				
				return -1;
			}
			else
			{
				//Check BSSID
				//if (IS_BROADCAST_BSSID(p->BSSID))
				//	return NDIS_STATUS_INVALID_DATA;
				if( OS_MEMORY_COMPARE( key_bssid, "\xff\xff\xff\xff\xff\xff", MAC_ADDR_LENGTH ) )
					return -1;

				//pairwise key: set the Temporal key of Phase 1
        		hal_set_mapping_key(&Adapter->sHwData,
       	        		            key_bssid, 0,1,
									ptx_tsc, prx_tsc,
           	            			key_type,
									key_len,
									key_material);

	    	    if (key_type == HAL_KEYTYPE_TKIP)
	        	{
					OS_MEMORY_COPY( psSME->tx_mic_key, tx_key, 8 );
					OS_MEMORY_COPY( psSME->rx_mic_key, rx_key, 8 );
            	}
				psSME->pairwise_key_ok = TRUE;
        	}
		}
		else
		{
			//Invalid data(XP design guidelines)
			#ifdef _PE_RX_DUMP_
			WBDEBUG(("Transmit bit(31) = 0, Pairwise bit(30) = 1.\n"));
			#endif
			return -1;
		}
	}
	return 0;
}

void sme_remove_default_key(void *pcore_data, int index)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	hal_remove_default_key(&Adapter->sHwData, index);
	
}

void sme_remove_mapping_key(void *pcore_data, UCHAR *pmac_addr)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	hal_remove_mapping_key(&Adapter->sHwData, pmac_addr);
	psSME->pairwise_key_ok = FALSE;
}

void sme_clear_all_mapping_key(void *pcore_data)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	hal_clear_all_mapping_key(&Adapter->sHwData);
	psSME->pairwise_key_ok = FALSE;
}

void sme_clear_all_default_key(void *pcore_data)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	hal_clear_all_default_key(&Adapter->sHwData);
	psSME->_dot11WEPDefaultKeyID = 0;
	psSME->group_key_ok = FALSE;
}

CHAR sme_set_remove_wep(void *pcore_data, ULONG key_index)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

    if ((key_index & 0x80000000) || ((key_index & 0x3fffffff) > 4))
    {
        return -1;
    }
    else
    {
		hal_remove_default_key(&Adapter->sHwData, key_index);
    }

    return 0;
}

/*
CHAR sme_set_preamble_mode(void *pcore_data, UCHAR mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psLOCAL->bPreambleMode = mode;
	return 0;
}

CHAR sme_get_preamble_mode(void *pcore_data, UCHAR *mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*mode = psLOCAL->bPreambleMode;
	return 0;
}

CHAR sme_get_preamble_type(void *pcore_data, UCHAR *type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*type = psLOCAL->boShortPreamble;
	return 0;
}

CHAR sme_set_slottime_mode(void *pcore_data, UCHAR mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psLOCAL->bSlotTimeMode = mode;
	return 0;
}

CHAR sme_get_slottime_mode(void *pcore_data, UCHAR *mode)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*mode = psLOCAL->bSlotTimeMode;
	return 0;
}

CHAR sme_get_slottime_type(void *pcore_data, UCHAR *type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*type = psLOCAL->boShortSlotTime;
	return 0;
}

CHAR sme_set_txrate_policy(void *pcore_data, UCHAR policy)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	//Adapter->Mds.TxRatePolicy = policy;
	return 0;
}

CHAR sme_get_txrate_policy(void *pcore_data, UCHAR *policy)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	// *policy = Adapter->Mds.TxRatePolicy;
	return 0;
}
*/

CHAR sme_get_cwmin_value(void *pcore_data, UCHAR *cwmin)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*cwmin = hal_get_cwmin( &Adapter->sHwData );
	return 0;
}

CHAR sme_get_cwmax_value(void *pcore_data, USHORT *cwmax)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*cwmax = hal_get_cwmax( &Adapter->sHwData );
	return 0;
}

//NDIS demands to be Radio On when set SSID OID, but be Radio Off when set Disassoc. OID.
//In this case, Radio On/Off will not influence TX/RX. The BSSID LIST OID will return empty if 
//Radio is off.
CHAR sme_get_ms_radio_mode(void *pcore_data, UCHAR * pMsRadioOff)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pMsRadioOff = psLOCAL->boMsRadioOff;
	return 0;
}

CHAR sme_set_ms_radio_mode(void *pcore_data, UCHAR boMsRadioOff)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("Radio off = %x\n", boMsRadioOff));
	#endif
	psLOCAL->boMsRadioOff = boMsRadioOff;
	return 0;
}

CHAR sme_get_radio_mode(void *pcore_data, psRadioOff pRadioOffData)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*pRadioOffData = psLOCAL->RadioOffStatus;
	return 0;
}

CHAR sme_set_radio_mode(void *pcore_data, RadioOff RadioOffData)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	UCHAR	boCurrentRadioOff, boDesiredRadioOff;

	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("Set h/w Radio off = %x\n", RadioOffData.boHwRadioOff));
	WBDEBUG(("Set s/w Radio off = %x\n", RadioOffData.boSwRadioOff));
	#endif
	if ((RadioOffData.boHwRadioOff == TRUE) || (RadioOffData.boSwRadioOff == TRUE))
		boDesiredRadioOff = TRUE;
	else
		boDesiredRadioOff = FALSE;
	if ((psLOCAL->RadioOffStatus.boHwRadioOff == TRUE) || (psLOCAL->RadioOffStatus.boSwRadioOff == TRUE))
		boCurrentRadioOff = TRUE;
	else
		boCurrentRadioOff = FALSE;
	psLOCAL->RadioOffStatus = RadioOffData;

	if (boDesiredRadioOff != boCurrentRadioOff)
	{
		if (boDesiredRadioOff == TRUE)
	{
		hal_set_radio_mode(&Adapter->sHwData, TRUE);
		OS_STOP( Adapter );	//return pending tx data
//20060627.1 WK		Adapter->sLocalPara.ShutDowned = TRUE;
		Adapter->Mds.TxPause = TRUE;  // Disable Tx frame
		Adapter->Mds.ScanTxPause = TRUE;
	}
	else
	{
		hal_set_radio_mode(&Adapter->sHwData, FALSE);
//20060627.1 WK		Adapter->sLocalPara.ShutDowned = FALSE;
		OS_SET_RESUME( Adapter );
		Adapter->Mds.TxPause = FALSE;  // Enable Tx frame
		Adapter->Mds.ScanTxPause = FALSE;
	}
	}
	return 0;
}

CHAR sme_get_network_type_in_use(void *pcore_data, UCHAR *ptype)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if (psLOCAL->wConnectedSTAindex != 0)
	{
		if (psBSS(psLOCAL->wConnectedSTAindex)->band == BAND_TYPE_OFDM_24)
		{
			if (psBSS(psLOCAL->wConnectedSTAindex)->boERP)
				*ptype = BAND_TYPE_OFDM_24;//OFDM 2.4G Hz
			else
				*ptype = BAND_TYPE_DSSS;//DSSS
		}
		else
		{
			//OFDM 5G Hz
			*ptype = BAND_TYPE_OFDM_5;
		}
	}
	else
	{
		switch (psLOCAL->bMacOperationMode)
		{
			case MODE_802_11_B:
				*ptype = BAND_TYPE_DSSS;
				break;
			case MODE_802_11_A:
				*ptype = BAND_TYPE_OFDM_5;
				break;
			default:
				*ptype = BAND_TYPE_OFDM_24;
				break;
		}
	}
	return 0;
}

CHAR sme_set_network_type_in_use(void *pcore_data, UCHAR type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psLOCAL->bMacOperationMode = type;
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("Set network type in use =%x\n", type));
	#endif
	return 0;
}

CHAR sme_set_reload_defaults(void *pcore_data, UCHAR reload_type)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	UCHAR EncryptStatus;

	if (reload_type == ENCRYPT_WEP)
	{
		sme_get_encryption_status(pcore_data, &EncryptStatus);
		if (EncryptStatus == ENCRYPT_WEP)
		{
			hal_clear_all_key(&Adapter->sHwData);
			psSME->pairwise_key_ok = FALSE;
			psSME->group_key_ok = FALSE;
			psSME->_dot11WEPDefaultKeyID = 0;
		}
		return 0;
	}
	return 0;
}


void sme_get_tx_power_level(void *pcore_data, ULONG *TxPower)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	//TODO : transfer from ?? to mW
	*TxPower = PowerDbToMw[MTOPARA_TXPOWER_INDEX()];
}

UCHAR sme_set_tx_power_level(void *pcore_data, ULONG TxPower)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;
	USHORT 	i = 0;

	//TODO : transfer from mW to ??
	for (i=0; i<32; i++)
	{
		if (TxPower >= PowerDbToMw[i])
			break;
	}
	MTOPARA_TXPOWER_INDEX() = i;
	hal_set_rf_power((&Adapter->sHwData), (UCHAR)MTOPARA_TXPOWER_INDEX());
	return 0;
}

void sme_get_antenna_count(void *pcore_data, ULONG *AntennaCount)
{
	//PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	*AntennaCount = 2;
}

void sme_get_rx_antenna(void *pcore_data, ULONG *RxAntenna)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if (MTO_ANT_DIVERSITY_ENABLE()  == 1)
		*RxAntenna = 0xffffffff;
	else
		*RxAntenna = psLOCAL->bAntennaNo;
}

UCHAR sme_set_rx_antenna(void *pcore_data, ULONG RxAntenna)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if (RxAntenna == 0xffffffff)
		MTO_ANT_DIVERSITY_ENABLE()  = 1;
	else
	{
		psLOCAL->bAntennaNo = (UCHAR)RxAntenna;
		hal_set_antenna_number(&Adapter->sHwData, psLOCAL->bAntennaNo);
	}
	return 0;
}

void sme_get_tx_antenna(void *pcore_data, ULONG *TxAntenna)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if (MTO_ANT_DIVERSITY_ENABLE()  == 1)
		*TxAntenna = 0xffffffff;
	else
		*TxAntenna = psLOCAL->bAntennaNo;
}

CHAR sme_set_tx_antenna(void *pcore_data, ULONG TxAntenna)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if (TxAntenna == 0xffffffff)
		MTO_ANT_DIVERSITY_ENABLE()  = 1;
	else
	{
		psLOCAL->bAntennaNo = (UCHAR)TxAntenna;
		hal_set_antenna_number(&Adapter->sHwData, psLOCAL->bAntennaNo);
	}
	return 0;
}

CHAR sme_set_IBSS_chan(void *pcore_data, ChanInfo chan)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	psLOCAL->IbssChanSetting.band = chan.band;
	psLOCAL->IbssChanSetting.ChanNo = chan.ChanNo;
	//The real channel setting must consider RF type, region, and modulation
	//type parameters.
	GetIbssChan(Adapter);
	//WBDEBUG((" ------ The IBSS channel is: band= %d, no=%d\n", psSME->IbssChan.band, psSME->IbssChan.ChanNo));
	return 0;
}


CHAR sme_set_IE_append(void *pcore_data, PUCHAR buffer, USHORT buf_len)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)pcore_data;

	if( buf_len >= MAX_IE_APPEND_SIZE )
		return -1; // out of buffer

	if( buf_len ) // Using 0 for disable IE append
		OS_MEMORY_COPY( psLOCAL->IE_Append_data, buffer, buf_len );
	psLOCAL->IE_Append_size = buf_len;

	return 0;
}


